import 'dart:convert';
import 'dart:math' as math;
import 'package:flutter/foundation.dart';

/// JSON工具类，用于处理JSON相关的辅助功能
class JsonUtils {
  /// 启用详细日志
  static bool enableVerboseLogging = true;
  
  /// 是否分段输出长日志
  static bool enableChunkedLogging = true;
  
  /// 记录详细日志
  static void _log(String message) {
    if (enableVerboseLogging) {
      if (enableChunkedLogging && message.length > 500) {
        // 分段输出长消息，避免被截断
        _logLongMessage(message);
      } else {
        debugPrint('JsonUtils: $message');
      }
    }
  }
  
  /// 分段输出长消息
  static void _logLongMessage(String message) {
    const int chunkSize = 500; // 每段长度
    
    int index = 0;
    final int totalChunks = (message.length / chunkSize).ceil();
    
    while (index < message.length) {
      final int end = math.min(index + chunkSize, message.length);
      final String chunk = message.substring(index, end);
      
      debugPrint('JsonUtils [${(index ~/ chunkSize) + 1}/$totalChunks]: $chunk');
      
      index += chunkSize;
    }
  }
  
  /// 分析并记录解析后的JSON结构
  static void logJsonStructure(dynamic json, {String prefix = ''}) {
    if (!enableVerboseLogging) return;
    
    if (json is Map) {
      _log('$prefix结构分析: Map包含 ${json.length} 个键');
      
      // 只记录前10个键，避免日志过长
      final keys = json.keys.take(10).toList();
      _log('$prefix键列表(最多10个): ${keys.join(', ')}${json.length > 10 ? '... 等${json.length - 10}个' : ''}');
      
      // 分析每个键的值类型
      Map<String, String> valueTypes = {};
      json.forEach((key, value) {
        String type = '未知';
        if (value == null) {
          type = 'null';
        } else if (value is String) {
          type = 'String(${value.length}字符)';
        } else if (value is Map) {
          type = 'Map(${value.length}项)';
        } else if (value is List) {
          type = 'List(${value.length}项)';
        } else {
          type = value.runtimeType.toString();
        }
        valueTypes[key.toString()] = type;
      });
      
      // 每个键单独一行记录
      valueTypes.forEach((key, type) {
        _log('$prefix - "$key": $type');
      });
    } else if (json is List) {
      _log('$prefix结构分析: List包含 ${json.length} 个元素');
      
      if (json.isNotEmpty) {
        // 分析前几个元素的类型
        final sampleSize = math.min(5, json.length);
        final samples = json.take(sampleSize).toList();
        
        for (int i = 0; i < samples.length; i++) {
          final value = samples[i];
          String type;
          
          if (value == null) {
            type = 'null';
          } else if (value is Map) {
            type = 'Map(${value.length}项)';
            // 递归分析第一个元素的详细结构
            if (i == 0 && value.isNotEmpty) {
              logJsonStructure(value, prefix: '$prefix  元素[0] > ');
            }
          } else if (value is List) {
            type = 'List(${value.length}项)';
          } else {
            type = value.runtimeType.toString();
          }
          
          _log('$prefix - 元素[$i]: $type');
        }
        
        if (json.length > sampleSize) {
          _log('$prefix - ... 等${json.length - sampleSize}个元素');
        }
      }
    } else {
      _log('$prefix结构分析: ${json.runtimeType} 类型的值');
    }
  }
  
  /// 解析带转义字符的JSON字符串
  /// 处理类似于 "{\n  \"properties\": [...  ]}" 这样的数据
  static Map<String, dynamic> parseEscapedJsonString(String jsonString, {bool removeControlChars = true}) {
    _log('开始解析JSON字符串，长度: ${jsonString.length}字符');
    
    try {
      // 清理字符串前的不可见字符和引号
      jsonString = jsonString.trim();
      if (jsonString.isEmpty) {
        _log('JSON字符串为空');
        return {};
      }
      
      // 去除可能存在的BOM标记
      if (jsonString.startsWith('\uFEFF')) {
        _log('检测到BOM标记，已移除');
        jsonString = jsonString.substring(1);
      }
      
      // 先检查是否以{或[开头
      if (!jsonString.startsWith('{') && !jsonString.startsWith('[')) {
        // 可能有额外的字符在开头，尝试找到第一个{或[
        final startBrace = jsonString.indexOf('{');
        final startBracket = jsonString.indexOf('[');
        
        if (startBrace >= 0 && (startBracket < 0 || startBrace < startBracket)) {
          _log('JSON字符串不以{开头，已跳过前$startBrace个字符');
          jsonString = jsonString.substring(startBrace);
        } else if (startBracket >= 0) {
          _log('JSON字符串不以[开头，已跳过前$startBracket个字符');
          jsonString = jsonString.substring(startBracket);
        }
      }
      
      // 如果需要，移除所有控制字符
      if (removeControlChars) {
        String before = jsonString;
        jsonString = _removeOrEscapeControlChars(jsonString);
        if (before != jsonString) {
          _log('已移除控制字符，处理前后长度变化: ${before.length} -> ${jsonString.length}');
        }
      }
      
      // 首先尝试直接解析
      final result = jsonDecode(jsonString);
      _log('直接解析JSON成功！结果类型: ${result.runtimeType}');
      
      if (result is Map) {
        _log('解析结果包含 ${result.length} 个顶级键');
        if (result.isNotEmpty) {
          _log('顶级键: ${result.keys.join(', ')}');
        }
        
        // 分析并记录解析后的结构
        logJsonStructure(result);
      } else if (result is List) {
        _log('解析结果是列表，包含 ${result.length} 个元素');
        
        // 分析并记录解析后的结构
        logJsonStructure(result);
      }
      
      return result is Map<String, dynamic> ? result : Map<String, dynamic>.from(result as Map);
    } catch (e) {
      _log('直接解析JSON失败，尝试处理转义字符: $e');
      
      try {
        // 如果直接解析失败，可能是因为字符串本身已经包含了转义字符
        // 尝试先处理常见的转义序列
        String decodedString = jsonString;
        
        // 以下转换必须按特定顺序进行，避免互相干扰
        // 处理双反斜杠先于单反斜杠
        decodedString = decodedString.replaceAll('\\\\', '\\');
        decodedString = decodedString.replaceAll('\\n', '\n');
        decodedString = decodedString.replaceAll('\\r', '\r');
        decodedString = decodedString.replaceAll('\\t', '\t');
        decodedString = decodedString.replaceAll('\\"', '"');
        decodedString = decodedString.replaceAll('\\/', '/');
        
        _log('处理了常见转义序列');
        
        // 强制移除所有控制字符
        if (removeControlChars) {
          String before = decodedString;
          decodedString = _removeOrEscapeControlChars(decodedString);
          if (before != decodedString) {
            _log('第二阶段：已移除控制字符，处理前后长度变化: ${before.length} -> ${decodedString.length}');
          }
        }
        
        // 输出处理后的字符串前几个字符，用于调试
        _log('处理转义后的前20个字符: ${decodedString.substring(0, math.min(20, decodedString.length))}');
        
        final result = jsonDecode(decodedString);
        _log('处理转义后解析成功！结果类型: ${result.runtimeType}');
        
        if (result is Map) {
          _log('解析结果包含 ${result.length} 个顶级键');
          if (result.isNotEmpty) {
            _log('顶级键: ${result.keys.join(', ')}');
          }
          
          // 分析并记录解析后的结构
          logJsonStructure(result);
        } else if (result is List) {
          _log('解析结果是列表，包含 ${result.length} 个元素');
          
          // 分析并记录解析后的结构
          logJsonStructure(result);
        }
        
        return result is Map<String, dynamic> ? result : Map<String, dynamic>.from(result as Map);
      } catch (e) {
        _log('处理转义字符后解析JSON仍然失败: $e');
        
        try {
          // 最后尝试处理原始字面量JSON字符串 - 这种字符串在字面上还保留着\n, \t等，需要特殊处理
          if (jsonString.contains('\\n') || jsonString.contains('\\"')) {
            // 创建一个原始字符串，移除所有转义符号的影响
            String rawJson = jsonString;
            
            // 如果字符串被引号包裹，先去除
            if ((rawJson.startsWith('"') && rawJson.endsWith('"')) || 
                (rawJson.startsWith("'") && rawJson.endsWith("'"))) {
              _log('检测到字符串被引号包裹，已移除外层引号');
              rawJson = rawJson.substring(1, rawJson.length - 1);
            }
            
            // 尝试以字面量的方式处理
            // 例如：将 "\n" 视为两个字符而不是换行符
            String processedJson = _processRawJsonLiteral(rawJson);
            _log('已处理原始JSON字面量');
            
            // 强制移除所有控制字符
            if (removeControlChars) {
              String before = processedJson;
              processedJson = _removeOrEscapeControlChars(processedJson);
              if (before != processedJson) {
                _log('第三阶段：已移除控制字符，处理前后长度变化: ${before.length} -> ${processedJson.length}');
              }
            }
            
            // 输出处理后的字符串前几个字符，用于调试
            _log('字面量处理后的前20个字符: ${processedJson.substring(0, math.min(20, processedJson.length))}');
            
            final result = jsonDecode(processedJson);
            _log('字面量处理后解析成功！结果类型: ${result.runtimeType}');
            
            if (result is Map) {
              _log('解析结果包含 ${result.length} 个顶级键');
              if (result.isNotEmpty) {
                _log('顶级键: ${result.keys.join(', ')}');
              }
              
              // 分析并记录解析后的结构
              logJsonStructure(result);
            } else if (result is List) {
              _log('解析结果是列表，包含 ${result.length} 个元素');
              
              // 分析并记录解析后的结构
              logJsonStructure(result);
            }
            
            return result is Map<String, dynamic> ? result : Map<String, dynamic>.from(result as Map);
          }
          
          // 最后尝试强制清理模式
          _log('尝试强制清理模式...');
          final forceCleaned = _forceCleanJsonString(jsonString);
          
          // 输出处理后的字符串前几个字符，用于调试
          if (forceCleaned.isNotEmpty) {
            _log('强制清理后的前20个字符: ${forceCleaned.substring(0, math.min(20, forceCleaned.length))}');
            
            final result = jsonDecode(forceCleaned);
            _log('强制清理后解析成功！结果类型: ${result.runtimeType}');
            
            if (result is Map) {
              _log('解析结果包含 ${result.length} 个顶级键');
              if (result.isNotEmpty) {
                _log('顶级键: ${result.keys.join(', ')}');
              }
              
              // 分析并记录解析后的结构
              logJsonStructure(result);
            }
            
            return result is Map<String, dynamic> ? result : Map<String, dynamic>.from(result as Map);
          }
          
          throw Exception('无法识别的JSON格式');
        } catch (e) {
          _log('所有解析方法都失败: $e');
          return {}; // 返回空对象
        }
      }
    }
  }
  
  /// 强制清理JSON字符串，移除所有可能导致解析错误的字符
  static String _forceCleanJsonString(String input) {
    try {
      // 首先尝试标准化JSON
      final StringBuffer buffer = StringBuffer();
      bool inString = false;
      bool escaped = false;
      int processedChars = 0;
      int replacedChars = 0;
      
      for (int i = 0; i < input.length; i++) {
        final char = input[i];
        processedChars++;
        
        // 如果当前在字符串中
        if (inString) {
          if (escaped) {
            // 如果是转义字符后面的字符
            escaped = false;
            buffer.write(char);
          } else if (char == '\\') {
            // 遇到转义字符
            escaped = true;
            buffer.write(char);
          } else if (char == '"') {
            // 字符串结束
            inString = false;
            buffer.write(char);
          } else if (char.codeUnitAt(0) < 32) {
            // 控制字符处理 - 在字符串中替换为空格
            buffer.write(' ');
            replacedChars++;
          } else {
            // 普通字符
            buffer.write(char);
          }
        } else {
          // 不在字符串中
          if (char == '"') {
            // 开始一个新字符串
            inString = true;
            buffer.write(char);
          }
          // 非字符串中的控制字符直接忽略
          else if (char.codeUnitAt(0) >= 32 || char == '\n' || char == '\r' || char == '\t') {
            buffer.write(char);
          } else {
            replacedChars++;
          }
        }
      }
      
      _log('强制清理处理了 $processedChars 个字符，替换了 $replacedChars 个问题字符');
      return buffer.toString();
    } catch (e) {
      _log('强制清理JSON失败: $e');
      return input; // 如果清理失败，返回原始字符串
    }
  }
  
  /// 移除或转义JSON中的控制字符
  static String _removeOrEscapeControlChars(String input) {
    // 正则表达式匹配所有控制字符(ASCII值小于32的字符，除了允许的空白字符)
    // 在JSON字符串中，只有\n, \r, \t, \f, \b是允许的(被转义)，其他的控制字符必须被移除
    final controlCharsPattern = RegExp(r'[\x00-\x08\x0B-\x0C\x0E-\x1F]');
    
    // 查找所有匹配项
    final matches = controlCharsPattern.allMatches(input);
    if (matches.isNotEmpty) {
      _log('检测到 ${matches.length} 个控制字符，将被移除或替换');
    }
    
    // 替换为空字符串(移除)
    return input.replaceAll(controlCharsPattern, ' ');
  }
  
  /// 处理原始JSON字面量字符串
  /// 例如将 "{\\"key\\":\\"value\\"}" 转换为 正确的JSON字符串
  static String _processRawJsonLiteral(String rawJson) {
    // 创建一个字符构建器
    StringBuffer buffer = StringBuffer();
    bool inEscape = false;
    int processedChars = 0;
    int escapedChars = 0;
    
    // 逐字符处理
    for (int i = 0; i < rawJson.length; i++) {
      String char = rawJson[i];
      processedChars++;
      
      if (inEscape) {
        escapedChars++;
        // 当前字符是转义后的字符
        switch (char) {
          case 'n': buffer.write('\n'); break;
          case 't': buffer.write('\t'); break;
          case 'r': buffer.write('\r'); break;
          case 'f': buffer.write('\f'); break;
          case 'b': buffer.write('\b'); break;
          case '"': buffer.write('"'); break;
          case "'": buffer.write("'"); break;
          case '\\': buffer.write('\\'); break;
          case '/': buffer.write('/'); break;
          default: 
            // 其他未识别的转义序列，保持原样
            buffer.write('\\$char');
        }
        inEscape = false;
      } else if (char == '\\') {
        // 遇到转义字符
        inEscape = true;
        buffer.write(char);
      } else {
        // 普通字符
        buffer.write(char);
      }
    }
    
    // 如果最后一个字符是转义符号，添加它本身
    if (inEscape) {
      buffer.write('\\');
    }
    
    _log('处理了 $processedChars 个字符，其中 $escapedChars 个转义字符');
    return buffer.toString();
  }
  
  /// 将任意对象转换为Map<String, dynamic>
  static Map<String, dynamic> toMap(dynamic obj) {
    if (obj == null) return {};
    
    try {
      if (obj is Map<String, dynamic>) {
        _log('对象已经是Map<String, dynamic>类型');
        return obj;
      } else if (obj is Map) {
        _log('对象是Map类型，但需要转换为Map<String, dynamic>');
        return Map<String, dynamic>.from(obj);
      } else if (obj is String) {
        _log('对象是String类型，尝试解析为JSON');
        return parseEscapedJsonString(obj, removeControlChars: true);
      } else {
        // 尝试使用jsonEncode/jsonDecode循环转换
        _log('对象是其他类型(${obj.runtimeType})，尝试通过JSON编解码转换');
        String jsonStr = jsonEncode(obj);
        return jsonDecode(jsonStr);
      }
    } catch (e) {
      _log('转换对象到Map失败: $e');
      return {};
    }
  }
  
  /// 格式化JSON对象为美观的字符串
  static String formatJsonString(dynamic json) {
    const JsonEncoder encoder = JsonEncoder.withIndent('  ');
    try {
      // 如果是字符串，先尝试解析
      if (json is String) {
        try {
          final parsedJson = jsonDecode(json);
          return encoder.convert(parsedJson);
        } catch (e) {
          // 如果解析失败，直接返回原字符串
          _log('格式化失败，无法解析字符串为JSON: $e');
          return json;
        }
      } 
      // 如果是Map，直接转换
      else if (json is Map) {
        return encoder.convert(json);
      }
      // 其他类型，尝试转换
      return encoder.convert(json);
    } catch (e) {
      _log('格式化JSON失败: $e');
      return json.toString();
    }
  }
  
  /// 安全地从Map中获取值，避免类型转换错误
  static T? getValueSafely<T>(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value == null) return null;
    
    try {
      if (value is T) return value;
      
      // 尝试基本类型转换
      if (T == int && value is String) {
        return int.tryParse(value) as T?;
      } else if (T == double && value is String) {
        return double.tryParse(value) as T?;
      } else if (T == bool && value is String) {
        return (value.toLowerCase() == 'true') as T?;
      } else if (T == String) {
        return value.toString() as T;
      }
    } catch (e) {
      _log('转换类型失败 $key: $e');
    }
    
    return null;
  }
} 